package com.easyattendance.services;


import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Random;

import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.easyattendance.model.ClassUser;
import com.easyattendance.model.Teacher;
import com.easyattendance.model.User;
import com.easyattendance.util.HibernateUtil;
import com.easyattendance.util.SecurePassword;

public class LoginService {

	public boolean authenticate(String emailId, String password) {
		User user = null;
		user = (User) getUserByUserId(emailId, "User");
		//password = SecurePassword.getHashValue(password);
		ClassUser class_user = null;
		class_user = (ClassUser) getClassUserByClassUserId(emailId, "ClassUser");
		password = SecurePassword.getHashValue(password);
		if (user != null) {			
			if(user.getPassword().equals(password)) {
				return true;
			}
			else {
				return false;
			}
		}
		else if(class_user!=null)
		{
			if(class_user.getPassword().equals(password)) {
				return true;
			}
			else {
				return false;
			}
			 
		}
		else {
			return false;
		}		
    }

    public Object getUserByUserId(String emailId, String type) {
        Session session = HibernateUtil.openSession();
        Transaction tx = null;
        User user = null;
        try {
            tx = session.getTransaction();
            tx.begin();
            Query query = session.createQuery("from "+type+" where email_id='"+emailId+"'");
            user = (User)query.uniqueResult();
            tx.commit();
        } catch (Exception e) {
            if (tx != null) {
                tx.rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
        return user;
    }
    
    public Object getClassUserByClassUserId(String emailId, String type) {
        Session session = HibernateUtil.openSession();
        Transaction tx = null;
        ClassUser class_user = null;
        try {
            tx = session.getTransaction();
            tx.begin();
            Query query = session.createQuery("from "+type+" where email_id='"+emailId+"'");
            class_user = (ClassUser)query.uniqueResult();
            tx.commit();
        } catch (Exception e) {
            if (tx != null) {
                tx.rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
        return class_user;
    }
    
    public boolean ifAlreadyExists(User newUser) {
		 boolean flag = false;
		 
		 Session session = HibernateUtil.openSession();
	      Transaction tx = null;
	      List users = null;
	      try{
	         tx = session.beginTransaction();
	         users = session.createQuery("FROM User").list(); 
	         for (Iterator iterator = users.iterator(); iterator.hasNext();){
	        	 User tempUser = (User) iterator.next(); 
	            if(tempUser.equals(newUser)) {
	            	System.out.println("User already exists");
	            	flag = true;
	            	break;
	            }
	             
	         }
	         tx.commit();
	      }catch (HibernateException e) {
	         if (tx!=null) tx.rollback();
	         e.printStackTrace(); 
	      }finally {
	         session.close(); 
	      }
		 
		 return flag;

	}
    
    public boolean ifAlreadyExists(String emailId) {
		 boolean flag = false;
		 
		 Session session = HibernateUtil.openSession();
	      Transaction tx = null;
	      List users = null;
	      try{
	         tx = session.beginTransaction();
	         users = session.createQuery("FROM User").list(); 
	         for (Iterator iterator = users.iterator(); iterator.hasNext();){
	        	 User tempUser = (User) iterator.next(); 
	            if(tempUser.getEmail_id().equals(emailId)) {
	            	System.out.println("user already exists");
	            	flag = true;
	            	break;
	            }
	             
	         }
	         tx.commit();
	      }catch (HibernateException e) {
	         if (tx!=null) tx.rollback();
	         e.printStackTrace(); 
	      }finally {
	         session.close(); 
	      }
		 
		 return flag;

	}
    
    public List<User> getListOfUser(){
        List<User> list = new ArrayList<User>();
        Session session = HibernateUtil.openSession();
        Transaction tx = null;        
        try {
            tx = session.getTransaction();
            tx.begin();
            list = session.createQuery("from User").list();                        
            tx.commit();
        } catch (Exception e) {
            if (tx != null) {
                tx.rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
        return list;
    }
    
    /* Method to CREATE a user in the database */
	   public synchronized boolean addNewUser(User user){
	      Session session = HibernateUtil.openSession();
	      Transaction tx = null;
	      boolean result=false;
	      
	      result = ifAlreadyExists(user);
	      
	      if(!result) {
	    	  try{
		    	  
		    	  tx = session.beginTransaction();
		    	  session.save(user);
		          tx.commit();
		      }catch (HibernateException e) {
		         if (tx!=null) tx.rollback();
		         e.printStackTrace(); 
		      }finally {
		         session.close(); 
		         System.out.println("Priya: new user added successfully FINALLY");
		      }
	    	  System.out.println("Priya: new user added successfully");
	    	  return true;
	      }
	      else {
	    	  return false;
	      }
	      
	      
	     
	   }
    
    public boolean authenticatePassword(String emailId, String oldPassword, String newPassword) {
    	User user = (User) getUserByUserId(emailId, "User");
    	oldPassword = SecurePassword.getHashValue(oldPassword);
    	
        if(user!=null && user.getEmail_id().equals(emailId) && user.getPassword().equals(oldPassword)){
        	newPassword = SecurePassword.getHashValue(newPassword);
        	updatePassword(user,newPassword);
            return true;
        }else{
        	System.out.println("Passwords do not match OR Email ID not entered correctly");
            return false;
        }
    }
    
    /* Method to UPDATE password of Login */
    public synchronized void updatePassword(User user, String newPassword){
    	Session session = HibernateUtil.openSession();
       Transaction tx = null;
       try{
          tx = session.beginTransaction();
          user.setPassword(newPassword);
 		  session.update(user); 
          tx.commit();
       }catch (HibernateException e) {
          if (tx!=null) tx.rollback();
          e.printStackTrace(); 
       }finally {
          session.close(); 
       }
    }
    
    public String getUserType(String userId) {
    	User user = null;
		user = (User) getUserByUserId(userId, "User");
		
		ClassUser class_user = null;
		class_user = (ClassUser) getClassUserByClassUserId(userId, "ClassUser");
		if(user!=null) {
			return user.getRole().getRole_name();
		}
		else if(class_user!=null)
		{
			return "Student";
		}
		else {
			return "Not Found";
		}
    }
    
    public boolean checkIsEnabled(String emailId)
    {
    	Session session = HibernateUtil.openSession();
        Transaction tx = null;
    	 User user=null;
    	 user = (User) getUserByUserId(emailId, "User");
    	 boolean status = false;
    	 
    	 ClassUser class_user=null;
    	 class_user = (ClassUser) getClassUserByClassUserId(emailId, "ClassUser");
    	 try {
             tx = session.getTransaction();
             tx.begin();
             if(user!=null)
            	 status=user.isEnabled();
             
             tx.commit();
         } catch (Exception e) {
             if (tx != null) {
                 tx.rollback();
             }
             e.printStackTrace();
         } finally {
             session.close();
         }
    	 
    	 if(class_user!= null)
    		  status=true;
   
       return status; 
    }
    
    public boolean checkIfLoggedInForFirstTime(String emailId)
    {
    	Session session = HibernateUtil.openSession();
        Transaction tx = null;
    	 User user=null;
    	 user = (User) getUserByUserId(emailId, "User");
    	 boolean status = false;
    	 
    	 try {
             tx = session.getTransaction();
             tx.begin();
             if(user!=null)
        	 {
            	 status=user.isFirstTimeLogin();
        		 
        		 if(status)
        		 {
        			 Query query=session.createQuery("update User set isFirstTimeLogin=:firstTimeLogin where email_id=:emailId");
        			 query.setParameter("firstTimeLogin",false);
        			 query.setParameter("emailId",emailId);
        			 
        			 int res=query.executeUpdate();
        		 }
        	 }
            
            
             tx.commit();
         } catch (Exception e) {
             if (tx != null) {
                 tx.rollback();
             }
             e.printStackTrace();
         } finally {
             session.close();
         }
   
       return status; 
    }
    
    public Object getUserBySecretKey(String token) {
        Session session = HibernateUtil.openSession();
        Transaction tx = null;
        User user = null;
        try {
            tx = session.getTransaction();
            tx.begin();
            Query query = session.createQuery("from User where secret_key='"+token+"'");
            user = (User)query.uniqueResult();
            tx.commit();
        } catch (Exception e) {
            if (tx != null) {
                tx.rollback();
            }
            e.printStackTrace();
        } finally {
            session.close();
        }
        return user;
    }
    
    public void updateEnabled(String token)
    {
    	Session session = HibernateUtil.openSession();
        Transaction tx = null;
    	 User user=null;
    	 user = (User) getUserBySecretKey(token);
    	 
    	 try {
             tx = session.getTransaction();
             tx.begin();
             if(user!=null)
             {
        			 Query query=session.createQuery("update User set enabled=:Enabled where secret_key=:token");
        			 query.setParameter("Enabled",true);
        			 query.setParameter("token",token);
        			
        			 int res=query.executeUpdate();
        			 
        	 }
            
             tx.commit();
         } catch (Exception e) {
             if (tx != null) {
                 tx.rollback();
             }
             e.printStackTrace();
         } finally {
             session.close();
         }
    }
    
    public void updateSecretKey(String token,String newToken)
    {
    	Session session = HibernateUtil.openSession();
        Transaction tx = null;
    	 User user=null;
    	 user = (User) getUserBySecretKey(token);
    	 
    	 try {
             tx = session.getTransaction();
             tx.begin();
             if(user!=null)
             {
        			 Query query=session.createQuery("update User set secret_key=:secret_key where email_id=:emailId");
        			 query.setParameter("secret_key",newToken);
        			 query.setParameter("emailId",user.getEmail_id());
        			 
        			 int res=query.executeUpdate();
        	 }
           
             tx.commit();
         } catch (Exception e) {
             if (tx != null) {
                 tx.rollback();
             }
             e.printStackTrace();
         } finally {
             session.close();
         }
    }
    
    public String generatePassword()
    {
    
    	final String charset = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@#$";
    	Random rand = new Random(System.currentTimeMillis());
        StringBuilder sb = new StringBuilder();
        int length=10;
        for (int i = 0; i < length; i++) {
            int pos = rand.nextInt(charset.length());
            sb.append(charset.charAt(pos));
        }
        
       return sb.toString();
    }
    
    public void SendMail(String emailId,String new_password)
	   {
		   final String username = "merin1590@gmail.com";
			final String password = "jesuschrist123";
	 
			Properties props = new Properties();
			props.put("mail.smtp.auth", "true");
			props.put("mail.smtp.starttls.enable", "true");
			props.put("mail.smtp.host", "smtp.gmail.com");
			props.put("mail.smtp.port", "587");
	 
			javax.mail.Session session = javax.mail.Session.getInstance(props,
			  new javax.mail.Authenticator() {
				protected PasswordAuthentication getPasswordAuthentication() {
					return new PasswordAuthentication(username, password);
				}
			  });
	 
			try {
	 
				Message message = new MimeMessage(session);
			
				message.setFrom(new InternetAddress("merin1590@gmail.com"));
				message.setRecipients(Message.RecipientType.TO,
				InternetAddress.parse(emailId));  
				/* message.setRecipients(Message.RecipientType.TO,
					InternetAddress.parse(teacherEmailId)); */
				message.setSubject("New password for EasyAttendance account");
					
				String msg_text="Hi, "+
						"\n\n Your new password is:  "+new_password+"\n Click the below link and use the new password to login to your EasyAttendance account"
						+"\n http://localhost:8080/Attendance/views/login.jsp";
				
						// Create the message part 
						MimeBodyPart messageBodyPart = new MimeBodyPart();

						// Fill the message
						messageBodyPart.setContent(msg_text,"text/html");

						MimeMultipart multipart = new MimeMultipart();
						multipart.addBodyPart(messageBodyPart);

						// Put parts in message
						message.setContent(multipart);
						message.setText(msg_text);
					Transport.send(message);
	 
				System.out.println("Mail sent!!");
	 
			} catch (MessagingException e) {
				throw new RuntimeException(e);
			} 

	   }
}
